#include "packetparser.h"

PacketParser::PacketParser(OnDataReceivedCallback onDataReceived) :
    mStatus(STATUS_FIND_PREFIX),
    mLen(0),
    mChecksum(0),
    mOnDataReceived(onDataReceived)
{
}

PacketParser::~PacketParser() = default;

void PacketParser::parser(QByteArray& buff) {
    int i;
    for (auto byte : buff) {
        switch (mStatus) {
        case STATUS_FIND_PREFIX:
            if (LEN_PREFIX == byte) {
                mStatus = STATUS_GET_LEN;
            }
            break;
        case STATUS_GET_LEN:
            if (byte) {
                mLen = byte;
                mStatus = STATUS_FIND_SUFFIX;
            } else {
                mStatus = STATUS_FIND_PREFIX;
            }
            break;
        case STATUS_FIND_SUFFIX:
            if (LEN_SUFFIX == byte) {
                mStatus = STATUS_RECV_DATA;
                mDecodedBuff.clear();
                mChecksum = 0;
            } else { // suffix not match
                if (LEN_PREFIX == static_cast<char>(mLen)) { // maybe mLen is prefix
                    mLen = byte;
                    mStatus = STATUS_FIND_SUFFIX;
                } else if (LEN_PREFIX == byte) { // maybe current byte is prefix
                    mStatus = STATUS_GET_LEN;
                } else {
                    mStatus = STATUS_FIND_PREFIX;
                }
            }
            break;
        case STATUS_RECV_DATA:
            mDecodedBuff.append(byte);
            mChecksum += static_cast<quint8>(byte);
            if (mDecodedBuff.size() >= mLen) {
                mStatus = STATUS_CHECKSUM;
            }
            break;
        case STATUS_CHECKSUM:
            if (static_cast<quint8>(byte) == mChecksum) {
                if (mOnDataReceived) {
                    mOnDataReceived(mDecodedBuff);
                }
            }
            mStatus = STATUS_FIND_PREFIX;
            break;
        default:
            ;// invalid status
        }
    }
}

QByteArray PacketParser::encode(QByteArray& data) {
    QByteArray encoded;
    encoded.append(LEN_PREFIX);
    encoded.append(data.size());
    encoded.append(LEN_SUFFIX);
    encoded.append(data);
    encoded.append(checksum(data));
    return encoded;
}

quint8 PacketParser::checksum(QByteArray& data) {
    quint8 sum = 0;
    for (auto byte : data) {
        sum += static_cast<quint8>(byte);
    }
    return sum;
}
